#ifndef _ARCH_PGTABLE_H
#define _ARCH_PGTABLE_H

#define PGD_SHIFT		20
#define PTRS_PER_PGD	4096
#define PGD_SIZE		(1UL << PGD_SHIFT)
#define PGD_MASK		(~(PGD_SIZE - 1))

#define PAGE_SHIFT		12
#define PTRS_PER_PTE	256
#define PAGE_SIZE		(1UL << PAGE_SHIFT)
#define PAGE_MASK		(~(PAGE_SIZE - 1))

#define PTE_TABLE_SIZE	(PTRS_PER_PTE * sizeof(pte_t))
#define PGD_TABLE_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))

/*
 * Hardware page table definitions 
 *
 */

#define MMU_TYPE_MASK	(3 << 0)
#define MMU_TYPE_SECT	(2 << 0)
#define MMU_TYPE_TABLE	(1 << 0)
#define MMU_TYPE_SMALL	(2 << 0)

#define MMU_DOMAIN_MASK		(0xf << 5)
#define MMU_DOMAIN(x)		((x) << 5)
#define MMU_DOMAIN_KERNEL	0

#define MMU_DOMAIN_NOACCESS	0
#define MMU_DOMAIN_CLIENT	1
#define MMU_DOMAIN_MANAGER	3

#define MMU_CB_MASK			(3 << 2)
#define MMU_BUFFERABLE		(1 << 2)
#define MMU_CACHEABLE		(1 << 3)
#define MMU_UNCACHED		(0)
#define MMU_BUFFERED		(MMU_BUFFERABLE)
#define MMU_WRITETHROUGH	(MMU_CACHEABLE)
#define MMU_WRITEBACK		(MMU_CACHEABLE | MMU_BUFFERABLE)

#define MMU_L1_BIT4			(1 << 4)

#define MMU_SECT_AP_MASK	(3 << 10)
#define MMU_SECT_AP_READ	(0 << 10)
#define MMU_SECT_AP_WRITE	(1 << 10)

#define MMU_SMALL_AP_MASK	(0xff << 4)
#define MMU_SMALL_AP_READ	(0x00 << 4)
#define MMU_SMALL_AP_WRITE	(0x55 << 4)

typedef uint32_t pgd_t;
typedef uint32_t pte_t;

extern pgd_t *__mboot_pgd_start;

#define __pgd(val)			((pgd_t)(val))
#define pgd_val(pgd)		((uint32_t)(pgd))
#define pgd_index(addr)     ((addr) >> PGD_SHIFT)
#define pgd_offset_k(addr)	(__mboot_pgd_start + pgd_index(addr))
#define pgd_none(pgd)		(!pgd_val(pgd))
#define set_pgd(pgd, val)	(*((pgd_t *)(pgd)) = __pgd(val))
#define pgd_clear(pgd)		(*((pgd_t *)(pgd)) = __pgd(0))

#define __pte(val)			((pte_t)(val))
#define pte_val(pte)		((uint32_t)(pte))
#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & PAGE_MASK)
#define pte_offset_k(addr)	((pte_t *)(pgd_val(*pgd_offset_k(addr)) & ~(PTE_TABLE_SIZE - 1)) + pte_index(addr))
#define pte_none(pte)		(!pte_val(pte))
#define set_pte(pte, val)	(*((pte_t *)(pte)) = __pte(val))
#define pte_clear(pte)		(*((pte_t *)(pte)) = __pte(0))

#endif /* _ARCH_PGTABLE_H */

